package top.chengdongqing.mishop.user.address

import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
import org.springframework.cache.annotation.CacheEvict
import org.springframework.cache.annotation.Cacheable
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional
import top.chengdongqing.mishop.common.exception.DeletionFailedException
import top.chengdongqing.mishop.common.exception.NotAcceptableException
import top.chengdongqing.mishop.entities.UserAddress
import top.chengdongqing.mishop.repositories.UserAddressRepository

@Service
class AddressService(private val addressRepository: UserAddressRepository) {

    @Cacheable(value = ["user:addresses"], key = "#userId")
    fun findAddresses(userId: Int): List<ShippingAddressDTO> {
        val addresses = addressRepository.findAllByUserIdOrderByCreatedAtDesc(userId)
        return addresses.map { ShippingAddressDTO.of(it) }
    }

    @CacheEvict(value = ["user:addresses"], key = "#userId")
    fun addAddress(userId: Int, addressDTO: ShippingAddressDTO) {
        val address = UserAddress(
            userId = userId,
            recipientName = addressDTO.recipientName,
            recipientPhone = addressDTO.recipientPhone,
            city = jacksonObjectMapper().writeValueAsString(addressDTO.city),
            address = addressDTO.address,
            label = addressDTO.label
        )
        addressRepository.save(address)
    }

    @CacheEvict(value = ["user:addresses"], key = "#userId")
    fun updateAddress(userId: Int, id: Int, addressDTO: ShippingAddressDTO) {
        val address = addressRepository.findByIdAndUserId(id, userId)
            ?: throw NotAcceptableException("收货地址不存在")

        address.recipientName = addressDTO.recipientName
        address.recipientPhone = addressDTO.recipientPhone
        address.city = jacksonObjectMapper().writeValueAsString(addressDTO.city)
        address.address = addressDTO.address
        address.label = addressDTO.label
        addressRepository.save(address)
    }

    @Transactional
    @CacheEvict(value = ["user:addresses"], key = "#userId")
    fun deleteAddress(userId: Int, id: Int) {
        if (addressRepository.deleteByIdAndUserId(id, userId) == 0) {
            throw DeletionFailedException("删除收货地址失败")
        }
    }
}